﻿using System;
using System.Collections.Generic;
using System.Text;
using MindFactorial.LaunchPoint.Common;

namespace MindFactorial.LaunchPoint.Console.Library
{
    /// <summary>
    /// Represents the base class for a plugin controller.  The usage of plugin controllers
    /// is strongly advised as they have no explicit user interface to them.  they should be used
    /// as the promary communication mechanism between the plugin surface and the underlying plugin/framework.
    /// </summary>
    public abstract class PluginController : IPluginController, IMessageProcessor , INamedObject<string>, IDeactivateListener
    {
        IConsolePlugIn _plugin = null;
        string _name = null;
        PluginSurface   _context       = null;
        IMenuPresenter  _menu       = null;
        PluginSurface   _content    = null;
        PluginSurface   _toolbar    = null;

        /// <summary>
        /// Gets the plugin specific context area object
        /// </summary>
        /// <typeparam name="CONTEXT_CLASS"></typeparam>
        /// <returns></returns>
        protected CONTEXT_CLASS ContextArea<CONTEXT_CLASS>() where CONTEXT_CLASS : PluginSurface 
        {
            return (CONTEXT_CLASS)_context;
        }

        /// <summary>
        /// Gets the plugin specific content area object
        /// </summary>
        /// <typeparam name="CONTENT_CLASS"></typeparam>
        /// <returns></returns>
        protected CONTENT_CLASS ContentArea<CONTENT_CLASS>() where CONTENT_CLASS : PluginSurface 
        {
            return (CONTENT_CLASS)_content;
        }

        /// <summary>
        /// gets the plugin specific plugin menu presenter
        /// </summary>
        /// <typeparam name="MENU_CLASS"></typeparam>
        /// <returns></returns>
        protected MENU_CLASS TopLevelMenu<MENU_CLASS>() where MENU_CLASS : IMenuPresenter 
        {
            return (MENU_CLASS)_menu;
        }

        /// <summary>
        /// gets the plugin specific toolbar surface object
        /// </summary>
        /// <typeparam name="TOOLBAR_CLASS"></typeparam>
        /// <returns></returns>
        protected TOOLBAR_CLASS Toolbar<TOOLBAR_CLASS>() where TOOLBAR_CLASS : PluginSurface 
        {
           return (TOOLBAR_CLASS)_toolbar;
        }

        internal void SetUIState(PluginSurface toolbar, PluginSurface context, PluginSurface content, IMenuPresenter menu)
        {            
            _menu =      menu;
            _toolbar =  toolbar;
            _context =  context;
            _content =  content;
            
        }

        /// <summary>
        /// Used to process broadcasted messages
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filter"></param>
        /// <param name="message"></param>
        public abstract void ProcessMessage<T>(string filter, T message);

        /// <summary>
        /// called to initialize an object this method is called by the framework
        /// at plugin load time, so preceeds all calles to loaded for any plugin surface.
        /// Each plugin should create at least one of these controllers to manage all interactions
        /// with bre and should only use surfaces to generate messages of recieve them
        /// </summary>
        public abstract void Init();

        /// <summary>
        /// Called when the plugin is activated from the registration area.  This is always the FIRST loaded called
        /// and should be overriden in the derived class to do any activity that must happen
        /// when the plugin is started.  This is of course different from Init() which is
        /// called shortly after the plugin is loaded into memory.  As such, this will happen ONLY
        /// when a plugin is in view by the user, whereas the Init call happen BEFORE the login page is even displayed!
        /// </summary>
        protected internal virtual void Load()
        {

        }

        internal void SetName(string name)
        {
            this._name = name;
        }

        /// <summary>
        /// Gets the plugin represented by this extender
        /// </summary>
        protected internal IConsolePlugIn PluginContext
        {
            get
            {
                return _plugin;
            }
            internal set
            {
                _plugin = value;
            }
        }


        #region INamedObject<string> Members

        /// <summary>
        /// The name of the controller
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        #endregion

        #region IDeactivateListener Members
        /// <summary>
        /// Called when the plugin is being deactivated (replaced by another other 
        /// plugin).  Should be overriden in base classes to provide appropriate 
        /// functionality
        /// </summary>
        public virtual void Deactivate()
        {
            
        }

        #endregion
    }
}
